package br.ykhan.sql.sqandal.builders;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import br.ykhan.sql.sqandal.elements.Column;
import br.ykhan.sql.sqandal.elements.Table;
import br.ykhan.sql.sqandal.joins.Join;

public class Select implements Query{

	private Set<Table> tables;
	private Set<Join> joins;
	private Set<Column> outputColumns;
	
	private QueryFormats queryFormat;
	
	public Select(Table table){
		tables = new HashSet<Table>();
		outputColumns = new HashSet<Column>();
		joins = new HashSet<Join>();
		
		tables.add(table);
	}

	/**
	 * Se a Table está contida dentro de um Join, ela não será adicionada. 
	 */
	public void addTable(Table table){

		for (Join jItem : joins)
			if (jItem.getTableJoined().equals(table)) return;

		tables.add(table);
	}
	
	public void addOutputColumn(Column column){
		outputColumns.add(column);
		addTable(column.getTable());
	}
	
	public void addJoin(Join join){

		for(Table tItem : tables)
			if(join.getTableJoined().equals(tItem)){
				tables.remove(tItem);
				break;
			}

		joins.add(join);
	}
	
	@Override
	public String toString() {
		
		if(queryFormat == null) queryFormat = QueryFormats.INLINE;
		
		StringBuffer sql = new StringBuffer();
		
		// SELECT
		sql.append("SELECT");

		// OUTPUT COLUMNS
		
		if(outputColumns.isEmpty())
			sql.append("\n\t*");
		else{
			
			Iterator<Column> it = outputColumns.iterator(); 
			
			int sizeColumnsList = outputColumns.size();
			int countColumns = 0;
			
			while(it.hasNext()){
				Column col = it.next();
				
				sql.append("\n\t"+col.getDeclarationName());
				
				if(++countColumns < sizeColumnsList) sql.append(",");
			}
		}
		
		// FROM
		
		sql.append("\nFROM");
		
		// TABLES

		Iterator<Table> it = tables.iterator();
		
		int sizeTablesList = tables.size();
		int countTables = 0;
		
		while(it.hasNext()){
			Table t = it.next();
			
			sql.append("\n\t"+t.getDeclarationName());
			
			if(++countTables < sizeTablesList) sql.append(",");
		}
		
		// JOINS
		
		for (Join j : joins)
			sql.append("\n\t\t"+j.getDeclarationName());
	
		// TODO : Usar QueryFormat para saber como indentar
		return sql.toString();
	}
	
	public void setQueryFormat(QueryFormats queryFormat) { this.queryFormat = queryFormat; }
	
	public QueryFormats getQueryFormat() {
		if(queryFormat == null) queryFormat = QueryFormats.INLINE;
		return queryFormat;
	}
	
}
